/*
 Syntax highlighting with language autodetection.
 http://softwaremaniacs.org/soft/highlight/
 */
var hljs = new function () {
    var LANGUAGES = {};
    var selected_languages = {};

    function escape(value) {
        return value.replace(/&/gm, '&amp;').replace(/</gm, '&lt;').replace(/>/gm, '&gt;')
    };
    function contains(array, item) {
        if (!array)return false;
        for (var i = 0; i < array.length; i++)if (array[i] == item)return true;
        return false
    };
    function langRe(language, value, global) {
        var mode = 'm' + (language.case_insensitive ? 'i' : '') + (global ? 'g' : '');
        return new RegExp(value, mode)
    };
    function findCode(pre) {
        var node;
        for (var i = 0; i < pre.childNodes.length; i++) {
            node = pre.childNodes[i];
            if (node.nodeName == 'CODE')return node;
            if (!(node.nodeType == 3 && node.nodeValue.match(/\s+/)))return null
        }
    };
    function blockText(block) {
        var result = '';
        for (var i = 0; i < block.childNodes.length; i++)if (block.childNodes[i].nodeType == 3)result += block.childNodes[i].nodeValue; else if (block.childNodes[i].nodeName == 'BR')result += '\n'; else result += blockText(block.childNodes[i]);
        return result
    };
    function blockLanguage(block) {
        var classes = block.className.split(/\s+/);
        classes = classes.concat(block.parentNode.className.split(/\s+/));
        for (var i = 0; i < classes.length; i++) {
            var class_ = classes[i].replace(/^language-/, '');
            if (class_ == 'no-highlight') {
                throw'No highlight'
            }
            ;
            if (LANGUAGES[class_]) {
                return class_
            }
        }
    };
    function nodeStream(node) {
        var result = [];
        (function (node, offset) {
            for (var i = 0; i < node.childNodes.length; i++) {
                if (node.childNodes[i].nodeType == 3)offset += node.childNodes[i].nodeValue.length; else if (node.childNodes[i].nodeName == 'BR')offset += 1; else {
                    result.push({event: 'start', offset: offset, node: node.childNodes[i]});
                    offset = arguments.callee(node.childNodes[i], offset);
                    result.push({event: 'stop', offset: offset, node: node.childNodes[i]})
                }
            }
            ;
            return offset
        })(node, 0);
        return result
    };
    function mergeStreams(stream1, stream2, value) {
        var processed = 0;
        var result = '';
        var nodeStack = [];

        function selectStream() {
            if (stream1.length && stream2.length) {
                if (stream1[0].offset != stream2[0].offset)return (stream1[0].offset < stream2[0].offset) ? stream1 : stream2; else return (stream1[0].event == 'start' && stream2[0].event == 'stop') ? stream2 : stream1
            } else {
                return stream1.length ? stream1 : stream2
            }
        };
        function open(node) {
            var result = '<' + node.nodeName.toLowerCase();
            for (var i = 0; i < node.attributes.length; i++) {
                var attribute = node.attributes[i];
                result += ' ' + attribute.nodeName.toLowerCase();
                if (attribute.nodeValue != undefined) {
                    result += '="' + escape(attribute.nodeValue) + '"'
                }
            }
            ;
            return result + '>'
        };
        function close(node) {
            return '</' + node.nodeName.toLowerCase() + '>'
        };
        while (stream1.length || stream2.length) {
            var current = selectStream().splice(0, 1)[0];
            result += escape(value.substr(processed, current.offset - processed));
            processed = current.offset;
            if (current.event == 'start') {
                result += open(current.node);
                nodeStack.push(current.node)
            } else if (current.event == 'stop') {
                var i = nodeStack.length;
                do {
                    i--;
                    var node = nodeStack[i];
                    result += close(node)
                } while (node != current.node);
                nodeStack.splice(i, 1);
                while (i < nodeStack.length) {
                    result += open(nodeStack[i]);
                    i++
                }
            }
        }
        ;
        result += value.substr(processed);
        return result
    };
    function highlight(language_name, value) {
        function compileSubModes(mode, language) {
            mode.sub_modes = [];
            for (var i = 0; i < mode.contains.length; i++) {
                for (var j = 0; j < language.modes.length; j++) {
                    if (language.modes[j].className == mode.contains[i]) {
                        mode.sub_modes[mode.sub_modes.length] = language.modes[j]
                    }
                }
            }
        };
        function subMode(lexem, mode) {
            if (!mode.contains) {
                return null
            }
            ;
            if (!mode.sub_modes) {
                compileSubModes(mode, language)
            }
            ;
            for (var i = 0; i < mode.sub_modes.length; i++) {
                if (mode.sub_modes[i].beginRe.test(lexem)) {
                    return mode.sub_modes[i]
                }
            }
            ;
            return null
        };
        function endOfMode(mode_index, lexem) {
            if (modes[mode_index].end && modes[mode_index].endRe.test(lexem))return 1;
            if (modes[mode_index].endsWithParent) {
                var level = endOfMode(mode_index - 1, lexem);
                return level ? level + 1 : 0
            }
            ;
            return 0
        };
        function isIllegal(lexem, mode) {
            return mode.illegalRe && mode.illegalRe.test(lexem)
        };
        function compileTerminators(mode, language) {
            var terminators = [];

            function addTerminator(re) {
                if (!contains(terminators, re)) {
                    terminators[terminators.length] = re
                }
            };
            if (mode.contains)for (var i = 0; i < language.modes.length; i++) {
                if (contains(mode.contains, language.modes[i].className)) {
                    addTerminator(language.modes[i].begin)
                }
            }
            ;
            var index = modes.length - 1;
            do {
                if (modes[index].end) {
                    addTerminator(modes[index].end)
                }
                ;
                index--
            } while (modes[index + 1].endsWithParent);
            if (mode.illegal) {
                addTerminator(mode.illegal)
            }
            ;
            var terminator_re = '(' + terminators[0];
            for (var i = 0; i < terminators.length; i++)terminator_re += '|' + terminators[i];
            terminator_re += ')';
            return langRe(language, terminator_re)
        };
        function eatModeChunk(value, index) {
            var mode = modes[modes.length - 1];
            if (!mode.terminators) {
                mode.terminators = compileTerminators(mode, language)
            }
            ;
            value = value.substr(index);
            var match = mode.terminators.exec(value);
            if (!match)return [value, '', true];
            if (match.index == 0)return ['', match[0], false]; else return [value.substr(0, match.index), match[0], false]
        };
        function keywordMatch(mode, match) {
            var match_str = language.case_insensitive ? match[0].toLowerCase() : match[0];
            for (var className in mode.keywordGroups) {
                if (!mode.keywordGroups.hasOwnProperty(className))continue;
                var value = mode.keywordGroups[className].hasOwnProperty(match_str);
                if (value)return [className, value]
            }
            ;
            return false
        };
        function processKeywords(buffer, mode) {
            if (!mode.keywords || !mode.lexems)return escape(buffer);
            if (!mode.lexemsRe) {
                var lexems_re = '(' + mode.lexems[0];
                for (var i = 1; i < mode.lexems.length; i++)lexems_re += '|' + mode.lexems[i];
                lexems_re += ')';
                mode.lexemsRe = langRe(language, lexems_re, true)
            }
            ;
            var result = '';
            var last_index = 0;
            mode.lexemsRe.lastIndex = 0;
            var match = mode.lexemsRe.exec(buffer);
            while (match) {
                result += escape(buffer.substr(last_index, match.index - last_index));
                var keyword_match = keywordMatch(mode, match);
                if (keyword_match) {
                    keyword_count += keyword_match[1];
                    result += '<span class="' + keyword_match[0] + '">' + escape(match[0]) + '</span>'
                } else {
                    result += escape(match[0])
                }
                ;
                last_index = mode.lexemsRe.lastIndex;
                match = mode.lexemsRe.exec(buffer)
            }
            ;
            result += escape(buffer.substr(last_index, buffer.length - last_index));
            return result
        };
        function processBuffer(buffer, mode) {
            if (mode.subLanguage && selected_languages[mode.subLanguage]) {
                var result = highlight(mode.subLanguage, buffer);
                keyword_count += result.keyword_count;
                relevance += result.relevance;
                return result.value
            } else {
                return processKeywords(buffer, mode)
            }
        };
        function startNewMode(mode, lexem) {
            var markup = mode.noMarkup ? '' : '<span class="' + mode.displayClassName + '">';
            if (mode.returnBegin) {
                result += markup;
                mode.buffer = ''
            } else if (mode.excludeBegin) {
                result += escape(lexem) + markup;
                mode.buffer = ''
            } else {
                result += markup;
                mode.buffer = lexem
            }
            ;
            modes[modes.length] = mode
        };
        function processModeInfo(buffer, lexem, end) {
            var current_mode = modes[modes.length - 1];
            if (end) {
                result += processBuffer(current_mode.buffer + buffer, current_mode);
                return false
            }
            ;
            var new_mode = subMode(lexem, current_mode);
            if (new_mode) {
                result += processBuffer(current_mode.buffer + buffer, current_mode);
                startNewMode(new_mode, lexem);
                relevance += new_mode.relevance;
                return new_mode.returnBegin
            }
            ;
            var end_level = endOfMode(modes.length - 1, lexem);
            if (end_level) {
                var markup = current_mode.noMarkup ? '' : '</span>';
                if (current_mode.returnEnd) {
                    result += processBuffer(current_mode.buffer + buffer, current_mode) + markup
                } else if (current_mode.excludeEnd) {
                    result += processBuffer(current_mode.buffer + buffer, current_mode) + markup + escape(lexem)
                } else {
                    result += processBuffer(current_mode.buffer + buffer + lexem, current_mode) + markup
                }
                ;
                while (end_level > 1) {
                    markup = modes[modes.length - 2].noMarkup ? '' : '</span>';
                    result += markup;
                    end_level--;
                    modes.length--
                }
                ;
                modes.length--;
                modes[modes.length - 1].buffer = '';
                if (current_mode.starts) {
                    for (var i = 0; i < language.modes.length; i++) {
                        if (language.modes[i].className == current_mode.starts) {
                            startNewMode(language.modes[i], '');
                            break
                        }
                    }
                }
                ;
                return current_mode.returnEnd
            }
            ;
            if (isIllegal(lexem, current_mode))throw'Illegal';
        };
        var language = LANGUAGES[language_name];
        var modes = [language.defaultMode];
        var relevance = 0;
        var keyword_count = 0;
        var result = '';
        try {
            var index = 0;
            language.defaultMode.buffer = '';
            do {
                var mode_info = eatModeChunk(value, index);
                var return_lexem = processModeInfo(mode_info[0], mode_info[1], mode_info[2]);
                index += mode_info[0].length;
                if (!return_lexem) {
                    index += mode_info[1].length
                }
            } while (!mode_info[2]);
            if (modes.length > 1)throw'Illegal';
            return {relevance: relevance, keyword_count: keyword_count, value: result}
        } catch (e) {
            if (e == 'Illegal') {
                return {relevance: 0, keyword_count: 0, value: escape(value)}
            } else {
                throw e;
            }
        }
    };
    function compileModes() {
        for (var i in LANGUAGES) {
            if (!LANGUAGES.hasOwnProperty(i))continue;
            var language = LANGUAGES[i];
            for (var j = 0; j < language.modes.length; j++) {
                var mode = language.modes[j];
                if (mode.begin)mode.beginRe = langRe(language, '^' + mode.begin);
                if (mode.end)mode.endRe = langRe(language, '^' + mode.end);
                if (mode.illegal)mode.illegalRe = langRe(language, '^(?:' + mode.illegal + ')');
                language.defaultMode.illegalRe = langRe(language, '^(?:' + language.defaultMode.illegal + ')');
                if (mode.relevance == undefined) {
                    mode.relevance = 1
                }
                ;
                if (!mode.displayClassName) {
                    mode.displayClassName = mode.className
                }
            }
        }
    };
    function compileKeywords() {
        function compileModeKeywords(mode) {
            if (!mode.keywordGroups) {
                for (var key in mode.keywords) {
                    if (!mode.keywords.hasOwnProperty(key))continue;
                    if (mode.keywords[key] instanceof Object)mode.keywordGroups = mode.keywords; else mode.keywordGroups = {'keyword': mode.keywords};
                    break
                }
            }
        };
        for (var i in LANGUAGES) {
            if (!LANGUAGES.hasOwnProperty(i))continue;
            var language = LANGUAGES[i];
            compileModeKeywords(language.defaultMode);
            for (var j = 0; j < language.modes.length; j++) {
                compileModeKeywords(language.modes[j])
            }
        }
    };
    function initialize() {
        if (initialize.called)return;
        initialize.called = true;
        compileModes();
        compileKeywords();
        selected_languages = LANGUAGES
    };
    function highlightBlock(block, tabReplace) {
        initialize();
        try {
            var text = blockText(block);
            var language = blockLanguage(block)
        } catch (e) {
            if (e == 'No highlight')return
        }
        ;
        if (language) {
            var result = highlight(language, text).value
        } else {
            var max_relevance = 0;
            for (var key in selected_languages) {
                if (!selected_languages.hasOwnProperty(key))continue;
                var lang_result = highlight(key, text);
                var relevance = lang_result.keyword_count + lang_result.relevance;
                if (relevance > max_relevance) {
                    max_relevance = relevance;
                    var result = lang_result.value;
                    language = key
                }
            }
        }
        ;
        if (result) {
            var class_name = block.className;
            if (!class_name.match(language)) {
                class_name += ' ' + language
            }
            ;
            var original = nodeStream(block);
            if (original.length) {
                var pre = document.createElement('pre');
                pre.innerHTML = result;
                result = mergeStreams(original, nodeStream(pre), text)
            }
            ;
            if (tabReplace) {
                result = result.replace(/^((<[^>]+>|\t)+)/gm, function (match, p1, offset, s) {
                    return p1.replace(/\t/g, tabReplace)
                })
            }
            ;
            var container = document.createElement('div');
            container.innerHTML = '<pre><code class="' + class_name + '">' + result + '</code></pre>';
            var environment = block.parentNode.parentNode;
            environment.replaceChild(container.firstChild, block.parentNode)
        }
    };
    function initHighlighting() {
        if (initHighlighting.called)return;
        initHighlighting.called = true;
        initialize();
        if (arguments.length) {
            for (var i = 0; i < arguments.length; i++) {
                if (LANGUAGES[arguments[i]]) {
                    selected_languages[arguments[i]] = LANGUAGES[arguments[i]]
                }
            }
        }
        ;
        var pres = document.getElementsByTagName('pre');
        for (var i = 0; i < pres.length; i++) {
            var code = findCode(pres[i]);
            if (code)highlightBlock(code, hljs.tabReplace)
        }
    };
    function initHighlightingOnLoad() {
        var original_arguments = arguments;
        var handler = function () {
            initHighlighting.apply(null, original_arguments)
        };
        if (window.addEventListener) {
            window.addEventListener('DOMContentLoaded', handler, false);
            window.addEventListener('load', handler, false)
        } else if (window.attachEvent)window.attachEvent('onload', handler); else window.onload = handler
    };
    this.LANGUAGES = LANGUAGES;
    this.initHighlightingOnLoad = initHighlightingOnLoad;
    this.highlightBlock = highlightBlock;
    this.initHighlighting = initHighlighting;
    this.IDENT_RE = '[a-zA-Z][a-zA-Z0-9_]*';
    this.UNDERSCORE_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_]*';
    this.NUMBER_RE = '\\b\\d+(\\.\\d+)?';
    this.C_NUMBER_RE = '\\b(0x[A-Za-z0-9]+|\\d+(\\.\\d+)?)';
    this.RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
    this.APOS_STRING_MODE = {
        className: 'string',
        begin: '\'',
        end: '\'',
        illegal: '\\n',
        contains: ['escape'],
        relevance: 0
    };
    this.QUOTE_STRING_MODE = {
        className: 'string',
        begin: '"',
        end: '"',
        illegal: '\\n',
        contains: ['escape'],
        relevance: 0
    };
    this.BACKSLASH_ESCAPE = {className: 'escape', begin: '\\\\.', end: '^', noMarkup: true, relevance: 0};
    this.C_LINE_COMMENT_MODE = {className: 'comment', begin: '//', end: '$', relevance: 0};
    this.C_BLOCK_COMMENT_MODE = {className: 'comment', begin: '/\\*', end: '\\*/'};
    this.HASH_COMMENT_MODE = {className: 'comment', begin: '#', end: '$'};
    this.C_NUMBER_MODE = {className: 'number', begin: this.C_NUMBER_RE, end: '^', relevance: 0}
}();
var initHighlightingOnLoad = hljs.initHighlightingOnLoad;